using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Rotempco.Core.ORM.Objects;
using Rotempco.Core.ORM.Logic;
using System.Reflection;

namespace Rotempco.Core.ORM.Logic
{
    public class DBNullHelper
    {
        internal static object ToNullable(object obj)
        {
            if (obj is PML)
                return (obj as PML).PMLToDBString();
            else if (obj == null)
                return DBNull.Value;
            else
                return obj;
        }

        public static bool TryToType(object obj, Type type, out object result)
        {
            result = null;

            try
            {
                result = ToType(obj, type);

                return true;
            }
            catch { }

            return false;
        }

        public static object ToType(object obj, Type type)
        {
            if (type == typeof(Enum))
            {
                return Convert.ToInt32(obj);
            }
            else if (type == typeof(Int16?))
            {
                return ToShort(obj);
            }
            else if (type == typeof(Int32?))
            {
                return ToInt(obj);
            }
            else if (type == typeof(Int64?))
            {
                return ToLong(obj);
            }
            else if (type == typeof(Double?))
            {
                return ToDouble(obj);
            }
            else if (type == typeof(String))
            {
                return ToString(obj);
            }
            else if (type == typeof(Boolean?))
            {
                return ToBool(obj);
            }
            else if (type == typeof(DateTime?))
            {
                return ToDateTime(obj);
            }
            else if (type == typeof(Int32))
            {
                return ToInt(obj).Value;
            }
            else if (type == typeof(Int64))
            {
                return ToLong(obj).Value;
            }
            else if (type == typeof(Double))
            {
                return ToDouble(obj).Value;
            }
            else if (type == typeof(Boolean))
            {
                return ToBool(obj).Value;
            }
            else if (type == typeof(DateTime))
            {
                return ToDateTime(obj).Value;
            }
            else if (type == typeof(byte[]))
            {
                return (obj) as byte[];
            }
            else if (type == typeof(PML))
            {
                return ToPML(obj);
            }
            else if (type == typeof(Guid?))
            {
                return ToGuid(obj);
            }
            else if (IsNullableEnum(type))
            {
                int? intValue = ToInt(obj);
                if (intValue.HasValue)
                {
                    TypeConverter convert = TypeDescriptor.GetConverter(type);
                    return convert.ConvertFrom(intValue.Value + "");
                }

                return null;
            }
            //else if (type.IsGenericType)
            //{
            //    if (type.GetGenericTypeDefinition() == typeof(Nullable<>))
            //    {
            //        if (type.GetGenericArguments().Length > 0 && type.GetGenericArguments()[0].IsEnum)
            //        {
            //            int? intValue = ToInt(obj);
            //            if (intValue.HasValue)
            //            {
            //                TypeConverter convert = TypeDescriptor.GetConverter(type);
            //                return convert.ConvertFrom(intValue.Value + "");
            //            }

            //            return null;
            //        }
            //    }
            //}

            return obj;
        }


        public static bool IsNullable(PropertyInfo propertyInfo)
        {
            return (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>));
        }


        public static bool IsNullableEnum(Type type)
        {
            if (type.IsGenericType)
            {
                if (type.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    if (type.GetGenericArguments().Length > 0 && type.GetGenericArguments()[0].IsEnum)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private static object ToNullableEnum(object obj)
        {
            return ((obj == DBNull.Value || obj == null) ? (object)null : Convert.ToInt32(obj));
        }

        private static string ToString(object obj)
        {
            return ((obj == DBNull.Value || obj == null) ? null : Convert.ToString(obj));
        }

        private static double? ToDouble(object obj)
        {
            return ((obj == DBNull.Value || obj == null) ? null : (double?)Convert.ToDouble(obj));
        }

        private static long? ToLong(object obj)
        {
            return ((obj == DBNull.Value || obj == null) ? null : (long?)Convert.ToInt64(obj));
        }

        private static short? ToShort(object obj)
        {
            return ((obj == DBNull.Value || obj == null) ? null : (short?)Convert.ToInt16(obj));
        }

        private static int? ToInt(object obj)
        {
            return ((obj == DBNull.Value || obj == null) ? null : (int?)Convert.ToInt32(obj));
        }

        private static bool? ToBool(object obj)
        {
            return ((obj == DBNull.Value || obj == null) ? null : (bool?)Convert.ToBoolean(obj));
        }

        private static DateTime? ToDateTime(object obj)
        {
            return ((obj == DBNull.Value || obj == null) ? null : (DateTime?)Convert.ToDateTime(obj));
        }

        private static PML ToPML(object obj)
        {
            if (obj is PML)
                return obj as PML;

            return ((obj == DBNull.Value || obj == null) ? null : PMLExtensions.DBStringToPML(obj.ToString()));
        }

        private static object ToGuid(object obj)
        {
            return ((obj == DBNull.Value || obj == null) ? (object)null : Guid.Parse(obj.ToString()));
        }
    }
}
